using System;
using System.Collections.Generic;

using SBPweb.Common.Caching;
using SBPweb.Common.Session;

using SBPweb.PROvibe.Resources.Warehouse.Role;

using SBPweb.PROvibe.Business.Logic;

namespace SBPweb.PROvibe.Business.Warehouse
{

	public class RoleFactory
	{
		#region Private static string constants

		private static string CACHEKEY_ROLES = "Warehouse.Roles";
		private static string CACHEKEY_ROLES_INDEX_ID = "Warehouse.Roles.Index.Id";
		private static string CACHEKEY_ROLES_INDEX_NAME = "Warehouse.Roles.Index.Name";

		private static string SESSIONKEY_ROLES = "_Repository.Roles";

		#endregion

		#region Private fields

		private static RoleRepository mRoleRepository
		{
			get
			{
				RoleRepository ret = SessionHandler.Get<RoleRepository>(SESSIONKEY_ROLES);

				if (ret == null)
				{
					ret = new RoleRepository(ConfigurationManager.ConnectionStrings.Warehouse);
					SessionHandler.Put<RoleRepository>(SESSIONKEY_ROLES, ret);
				}

				return ret;
			}
		}

		#endregion

		#region Constructor logic

		private RoleFactory()
		{
		}

		#endregion

		#region Repository handler methods

		#region Create

		public static Business.Entities.Role CreateRole(string name)
		{
			Resources.Entities.Role role = new Resources.Entities.Role();

			role.Name = name;

			mRoleRepository.Add(role);

			return ConvertResourcesEntity(role);
		}

		#endregion

		#region Read

		public static List<Entities.Role> ReadRoles()
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_ROLES))
			{
				return CacheHandler.Retrieve<List<Entities.Role>>(CACHEKEY_ROLES);
			}

			List<Entities.Role> roles = ConvertResourcesEntityList(mRoleRepository.GetRoles());

			if (isCached)
			{
				CacheHandler.Store<List<Entities.Role>>(CACHEKEY_ROLES, roles, ConfigurationManager.CacheExpirations.Warehouse.Roles);

				Dictionary<int, Entities.Role> indexId = new Dictionary<int, Entities.Role>();
				Dictionary<string, Entities.Role> indexName = new Dictionary<string, Entities.Role>();

				foreach (Entities.Role role in roles)
				{
					indexId.Add(role.Id, role);
					indexName.Add(role.Name, role);
				}

				CacheHandler.Store<Dictionary<int, Entities.Role>>(CACHEKEY_ROLES_INDEX_ID, indexId, ConfigurationManager.CacheExpirations.Warehouse.Roles);
				CacheHandler.Store<Dictionary<string, Entities.Role>>(CACHEKEY_ROLES_INDEX_NAME, indexName, ConfigurationManager.CacheExpirations.Warehouse.Roles);
			}

			return roles;
		}

		public static Entities.Role ReadRoleById(int roleId)
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;
			Dictionary<int, Entities.Role> index = null;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_ROLES_INDEX_ID))
			{
				index = CacheHandler.Retrieve<Dictionary<int, Entities.Role>>(CACHEKEY_ROLES_INDEX_ID);
				if (index.ContainsKey(roleId))
				{
					return index[roleId];
				}
			}

			Resources.Entities.Role resource = mRoleRepository.GetRoleById(roleId);
            Entities.Role role = null;
            if (resource != null)
            {
                role = ConvertResourcesEntity(resource);
            }

			if (index != null)
			{
				index.Add(roleId, role);
			}

			return role;
		}

		public static Entities.Role ReadRoleByName(string roleName)
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;
			Dictionary<string, Entities.Role> index = null;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_ROLES_INDEX_NAME))
			{
				index = CacheHandler.Retrieve<Dictionary<string, Entities.Role>>(CACHEKEY_ROLES_INDEX_NAME);
				if (index.ContainsKey(roleName))
				{
					return index[roleName];
				}
			}

			Resources.Entities.Role resource = mRoleRepository.GetRoleByName(roleName);
            Entities.Role role = null;
            if (resource != null)
            {
                role = ConvertResourcesEntity(resource);
            }

			if (index != null)
			{
				index.Add(roleName, role);
			}

			return role;
		}

		#endregion

		#region Update

		public static void UpdateRole(Entities.Role role)
		{
			mRoleRepository.Update(role);
		}

		#endregion

		#region Delete

		public static void DeleteRole(int roleId)
		{
			mRoleRepository.Remove(roleId);
		}

		public static void DeleteRole(Entities.Role role)
		{
			DeleteRole(role.Id);
		}

		#endregion

		#endregion

		#region Internal converter methods

		internal static List<Entities.Role> ConvertResourcesEntityList(List<Resources.Entities.Role> list)
		{
			return list.ConvertAll<Entities.Role>(new Converter<Resources.Entities.Role, Entities.Role>(ConvertResourcesEntity));
		}

		internal static Entities.Role ConvertResourcesEntity(Resources.Entities.Role role)
		{
			return new Entities.Role(role);
		}

		#endregion


	}

}
